Introducción a Pandas en los cuadernos de Jupyter

La estructura de Datos Serie

Arreglo unidimensional con etiquetas en los ejes (incluidas series de tiempo). Los parámetros de una Serie son: data (matriz, diccionario o escalar), index (arreglo de índices), dtype (numpy.dtype o None) y copy (booleano o por defecto False)


Importamos la biblioteca Pandas


In [1]:
import pandas as pd
pd.Series?


Podemos convertir una lista en una serie y pandas asigna de manera inmediata una lista de índices que empieza en 0.


In [2]:
animales = ['Tigre', 'Oso', 'Camello']
pd.Series(animales)


Out[2]:
0      Tigre
1        Oso
2    Camello
dtype: object

In [3]:
numeros = [1, 2, 3]
pd.Series(numeros)


Out[3]:
0    1
1    2
2    3
dtype: int64

In [4]:
animales = ['Tigre', 'Oso', None]
pd.Series(animales)


Out[4]:
0    Tigre
1      Oso
2     None
dtype: object


Es importante saber como NumPy y Pandas manejan los datos faltantes. En Python tenemos el tipo None para indicar un dato faltante. Si tenemos una lista de números, Pandas automáticamente convierte este valor None en un valor designado como NaN, que significa Not a Number.


In [5]:
numeros = [1, 2, None]
pd.Series(numeros)


Out[5]:
0    1.0
1    2.0
2    NaN
dtype: float64


Importamos la biblioteca NumPy. También es importante saber que NaN no es None. Cuando hacemos un test para saber si NaN es NaN tambien obtendremos False.


In [6]:
import numpy as np
np.nan == None


Out[6]:
False

In [7]:
np.nan == np.nan


Out[7]:
False


Se necesita la función especial isnan de NumPy para chequear la presencia de un no número en nuestros datos.


In [8]:
print(np.isnan(np.nan))
print(None is None)
print(np.nan is np.nan)


True
True
True


¿Cómo creamos una serie en Pandas? Podemos utilizar una estructura de datos diccionario con sus claves y convertirlo en una serie, donde los índices de la serie son las claves del diccionario.


In [9]:
deportes = {'Capoeira': 'Brasil',
          'Rayuela': 'Chile',
          'Pelota Vasca': 'País Vasco',
          'Béisbol': 'Cuba',
           'Rugby': 'Gales',
           'Golf': 'Escocia',
           'Corrida de Toros': 'España',
           'Sumo': 'Japón'}
s = pd.Series(deportes)
s


Out[9]:
Béisbol                   Cuba
Capoeira                Brasil
Corrida de Toros        España
Golf                   Escocia
Pelota Vasca        País Vasco
Rayuela                  Chile
Rugby                    Gales
Sumo                     Japón
dtype: object


Luego, podemos chequear la lista de índices con el atributo .index


In [10]:
s.index


Out[10]:
Index(['Béisbol', 'Capoeira', 'Corrida de Toros', 'Golf', 'Pelota Vasca',
       'Rayuela', 'Rugby', 'Sumo'],
      dtype='object')


En este otro ejemplo, pasamos directamente una lista con su conjunto de índices para crear la Serie.


In [11]:
s = pd.Series(['Tigre', 'Oso', 'Camello'], index=['India', 'America', 'Africa'])
s


Out[11]:
India        Tigre
America        Oso
Africa     Camello
dtype: object


Aquí tenemos un ejemplo de un elemento nuevo en la lista de índices que no tiene un valor asignado, no existe un país asociado al índice Natación y Pandas representa este valor faltante con NaN.


In [12]:
deportes = {'Capoeira': 'Brasil',
          'Rayuela': 'Chile',
          'Pelota Vasca': 'País Vasco',
          'Béisbol': 'Cuba',
           'Rugby': 'Gales',
           'Golf': 'Escocia',
           'Corrida de Toros': 'España',
           'Sumo': 'Japón'}
s = pd.Series(deportes, index=['Capoeira', 'Sumo', 'Pelota Vasca',  'Natación'])
s


Out[12]:
Capoeira            Brasil
Sumo                 Japón
Pelota Vasca    País Vasco
Natación               NaN
dtype: object

Búsqueda en una Serie


In [13]:
deportes = {'Capoeira': 'Brasil',
          'Rayuela': 'Chile',
          'Pelota Vasca': 'País Vasco',
          'Béisbol': 'Cuba',
           'Rugby': 'Gales',
           'Golf': 'Escocia',
           'Corrida de Toros': 'España',
           'Sumo': 'Japón'}
s = pd.Series(deportes)
s


Out[13]:
Béisbol                   Cuba
Capoeira                Brasil
Corrida de Toros        España
Golf                   Escocia
Pelota Vasca        País Vasco
Rayuela                  Chile
Rugby                    Gales
Sumo                     Japón
dtype: object


Podemos hacer búsquedas en las series por posición de índices o por etiqueta de índices. Si queremos hacer búsqueda por ubicación numérica (empezando desde 0) utilizamos el atributo iloc. Si por otra parte, hacemos búqueda por etiqueta de índice entonces usamos el atributo loc.


In [14]:
s.iloc[4]


Out[14]:
'País Vasco'

In [15]:
s.loc['Pelota Vasca']


Out[15]:
'País Vasco'


Pandas trata de que el código sea más legible. Si le pasamos por parámetro un valor numérico a la Serie esta se comportará como si la búsqueda se hace con el atributo iloc, si en cambio le pasamos un objeto, hará la búsqueda por etiqueta como con el atributo loc.


In [16]:
s[4]


Out[16]:
'País Vasco'

In [17]:
s['Pelota Vasca']


Out[17]:
'País Vasco'


¿Qué pasa cuando tenemos una lista de índices que son enteros?


In [18]:
deportes = {99: 'Brasil',
          100: 'Chile',
          101: 'País Vasco',
          102: 'Cuba',
           103: 'Gales',
           104: 'Escocia',
           105: 'España',
           106: 'Japón'}
s = pd.Series(deportes)
s


Out[18]:
99         Brasil
100         Chile
101    País Vasco
102          Cuba
103         Gales
104       Escocia
105        España
106         Japón
dtype: object


Cuando tenemos un caso como este es más seguro utilizar los atributos iloc o loc según sea el caso.


In [19]:
s[0] #Esta instrucción no llamará s.iloc[0] como esperaríamos y va a generar un error


---------------------------------------------------------------------------
KeyError                                  Traceback (most recent call last)
<ipython-input-19-6188cad29e89> in <module>()
----> 1 s[0] #Esta instrucción no llamará s.iloc[0] como esperaríamos y va a generar un error

/anaconda3/lib/python3.6/site-packages/pandas/core/series.py in __getitem__(self, key)
    621         key = com._apply_if_callable(key, self)
    622         try:
--> 623             result = self.index.get_value(self, key)
    624 
    625             if not is_scalar(result):

/anaconda3/lib/python3.6/site-packages/pandas/core/indexes/base.py in get_value(self, series, key)
   2558         try:
   2559             return self._engine.get_value(s, k,
-> 2560                                           tz=getattr(series.dtype, 'tz', None))
   2561         except KeyError as e1:
   2562             if len(self) > 0 and self.inferred_type in ['integer', 'boolean']:

pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_value()

pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_value()

pandas/_libs/index.pyx in pandas._libs.index.IndexEngine.get_loc()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.Int64HashTable.get_item()

pandas/_libs/hashtable_class_helper.pxi in pandas._libs.hashtable.Int64HashTable.get_item()

KeyError: 0

In [ ]:
s.iloc[0]

In [ ]:
s.loc[99]


Ya que sabemos hacer búsquedas en las Series, ahora vamos a trabajar con los datos (encontrar valores, resumir los datos o transformarlos).


In [20]:
s = pd.Series([105.00, 223.00, 5, 102.00, 27, -126])
s


Out[20]:
0    105.0
1    223.0
2      5.0
3    102.0
4     27.0
5   -126.0
dtype: float64


Una forma de trabajar es iterar sobre un conjunto de datos e invocar una operación de interés


In [21]:
total = 0
for elemento in s:
    total+=elemento
print(total)


336.0


Con NumPy podemos tener acceso a las funciones universales binarias o unarias (vectorizadas, cálculos más rápidos). En este ejemplo, np.sum hará la suma de todos los elementos en la serie.


In [22]:
import numpy as np

total = np.sum(s)
print(total)


336.0


También podemos generar una serie grande de números aleatorios y con el método .head() podemos desplegar un encabezado con los 5 primeros elementos de la serie y con len chequear el tamaño de la misma.


In [23]:
s = pd.Series(np.random.randint(0,1000,10000))
print(s.head())
print(len(s))


0     42
1    872
2    956
3    330
4      9
dtype: int64
10000


Los cuadernos de Jupyter tienen funciones mágicas que pueden ser útiles. Una de ellas es %%timeit que nos servirá para ver cuál de los dos métodos para sumar elementos de una serie es más rápido. Basta con tipear el símbolo % y la tecla Tab para obtener una lista de las funciones mágicas de Jupyter.


In [24]:
%%timeit -n 100
sumar = 0
for elemento in s:
    sumar+=elemento


803 µs ± 52.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [25]:
%%timeit -n 100
sumar = np.sum(s)


128 µs ± 21.9 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)


NumPy y Pandas tienen el broadcasting, se puede aplicar una operación a cada valor de la serie y modificarla.


In [26]:
s+=2 #Suma 2 a cada elemento de la serie usando broadcasting
s.head()


Out[26]:
0     44
1    874
2    958
3    332
4     11
dtype: int64


Una manera poco eficiente de hacer esto es iterar sobre cada elemento de la serie para hacer la suma. El método .iteritems() devuelve un iterador sobre los pares (key, value) (clave, valor) de un diccionario, en este caso de nuestra serie s.


In [27]:
for etiqueta, valor in s.iteritems():
    s.set_value(etiqueta, valor+2)
s.head()


/anaconda3/lib/python3.6/site-packages/ipykernel_launcher.py:2: FutureWarning: set_value is deprecated and will be removed in a future release. Please use .at[] or .iat[] accessors instead
  
Out[27]:
0     46
1    876
2    960
3    334
4     13
dtype: int64

In [ ]:
%%timeit -n 10
s = pd.Series(np.random.randint(0,1000,10000))
for etiqueta, valor in s.iteritems():
    s.loc[etiqueta]= valor+2

In [ ]:
%%timeit -n 10
s = pd.Series(np.random.randint(0,1000,10000))
s+=2


Podemos agregar elementos a una serie de la siguiente forma:


In [2]:
import pandas as pd
s = pd.Series([1, 2, 3])
s.loc['Animal'] = 'Oso'
s


Out[2]:
0           1
1           2
2           3
Animal    Oso
dtype: object


Este es un ejemplo de una serie donde los valores del conjunto de índices no son únicos. Esto hace que las tablas de datos funcionen diferente y es por ello que agregar nuevos elementos debe hacerse con el método append, que en primera instancia, no modificará la serie sino que devuelve una nueva serie con los elementos que se agregaron.


In [4]:
deportes_originales = pd.Series({'Capoeira': 'Brasil',
          'Rayuela': 'Chile',
          'Pelota Vasca': 'País Vasco',
          'Béisbol': 'Cuba',
           'Rugby': 'Gales',
           'Golf': 'Escocia',
           'Corrida de Toros': 'España',
           'Sumo': 'Japón'})
paises_que_aman_el_beisbol = pd.Series(['Venezuela',
                                      'USA',
                                      'Cuba',
                                      'Puerto Rico',
                                       'Dominicana'], 
                                   index=['Béisbol',
                                          'Béisbol',
                                          'Béisbol',
                                          'Béisbol',
                                          'Béisbol'])
todos_los_paises = deportes_originales.append(paises_que_aman_el_beisbol)

In [5]:
deportes_originales


Out[5]:
Béisbol                   Cuba
Capoeira                Brasil
Corrida de Toros        España
Golf                   Escocia
Pelota Vasca        País Vasco
Rayuela                  Chile
Rugby                    Gales
Sumo                     Japón
dtype: object

In [6]:
paises_que_aman_el_beisbol


Out[6]:
Béisbol      Venezuela
Béisbol            USA
Béisbol           Cuba
Béisbol    Puerto Rico
Béisbol     Dominicana
dtype: object

In [7]:
todos_los_paises


Out[7]:
Béisbol                    Cuba
Capoeira                 Brasil
Corrida de Toros         España
Golf                    Escocia
Pelota Vasca         País Vasco
Rayuela                   Chile
Rugby                     Gales
Sumo                      Japón
Béisbol               Venezuela
Béisbol                     USA
Béisbol                    Cuba
Béisbol             Puerto Rico
Béisbol              Dominicana
dtype: object

In [8]:
todos_los_paises.loc['Béisbol']


Out[8]:
Béisbol           Cuba
Béisbol      Venezuela
Béisbol            USA
Béisbol           Cuba
Béisbol    Puerto Rico
Béisbol     Dominicana
dtype: object

La estructura de datos DataFrame


El DataFrame o Tabla de Datos es el corazón de la biblioteca Pandas. Es el objeto primario para el análisis de datos. Es una especie de arreglo bidimensional con etiquetas en los ejes. En este ejemplo, crearemos tres diccionarios que serán luego las filas de nuestro DataFrame.


In [9]:
import pandas as pd
compra_1 = pd.Series({'Nombre': 'Adelis',
                        'Artículo comprado': 'Libro',
                        'Costo': 1200})
compra_2 = pd.Series({'Nombre': 'Miguel',
                        'Artículo comprado': 'Raspberry pi 3',
                        'Costo': 15000})
compra_3 = pd.Series({'Nombre': 'Jaime',
                        'Artículo comprado': 'Balón',
                        'Costo': 5000})
df = pd.DataFrame([compra_1, compra_2, compra_3], index=['Tienda 1', 'Tienda 1', 'Tienda 2'])
df.head()


Out[9]:
Artículo comprado Costo Nombre
Tienda 1 Libro 1200 Adelis
Tienda 1 Raspberry pi 3 15000 Miguel
Tienda 2 Balón 5000 Jaime


En un DataFrame también se puede extraer información usando los atributos loc y iloc.


In [10]:
df.loc['Tienda 2']


Out[10]:
Artículo comprado    Balón
Costo                 5000
Nombre               Jaime
Name: Tienda 2, dtype: object


También podemos chequear el tipo de dato usando la función type de Python.


In [11]:
type(df.loc['Tienda 2'])


Out[11]:
pandas.core.series.Series


En los DataFrame también se pueden tener listas de índices no únicos. En el ejemplo, hay dos índices con el mismo nombre Tienda 1.


In [12]:
df.loc['Tienda 1']


Out[12]:
Artículo comprado Costo Nombre
Tienda 1 Libro 1200 Adelis
Tienda 1 Raspberry pi 3 15000 Miguel


También podemos seleccionar columnas agregando un parámetro extra al atributo loc.


In [13]:
df.loc['Tienda 1', 'Costo']


Out[13]:
Tienda 1     1200
Tienda 1    15000
Name: Costo, dtype: int64


Usar el atributo .T para obtener la transpuesta del DataFrame o Tabla de Datos.


In [14]:
df.T


Out[14]:
Tienda 1 Tienda 1 Tienda 2
Artículo comprado Libro Raspberry pi 3 Balón
Costo 1200 15000 5000
Nombre Adelis Miguel Jaime


Usando .T.loc[] se puede seleccionar una columna usando como parámetro la etiqueta de su nombre.


In [15]:
df.T.loc['Costo']


Out[15]:
Tienda 1     1200
Tienda 1    15000
Tienda 2     5000
Name: Costo, dtype: object

In [17]:
df['Costo']


Out[17]:
Tienda 1     1200
Tienda 1    15000
Tienda 2     5000
Name: Costo, dtype: int64

In [18]:
df.loc['Tienda 1']['Costo']


Out[18]:
Tienda 1     1200
Tienda 1    15000
Name: Costo, dtype: int64


loc también tiene soporte para rebanar o seleccionar del DataFrame con la notación []


In [19]:
df.loc[:,['Nombre', 'Costo']]


Out[19]:
Nombre Costo
Tienda 1 Adelis 1200
Tienda 1 Miguel 15000
Tienda 2 Jaime 5000


También podemos eliminar datos del DataFrame con la función drop(). Esta función toma un solo parámetro que es el índice del conjunto de datos que deseamos eliminar.


In [20]:
df.drop('Tienda 1')


Out[20]:
Artículo comprado Costo Nombre
Tienda 2 Balón 5000 Jaime


Podemos ver que nuestro DataFrame original sigue intacto. Solo hicimos una extracción de información.


In [21]:
df


Out[21]:
Artículo comprado Costo Nombre
Tienda 1 Libro 1200 Adelis
Tienda 1 Raspberry pi 3 15000 Miguel
Tienda 2 Balón 5000 Jaime


También podemos hacer una copia del DataFrame con la función copy() para guardar la extracción de información.


In [24]:
copiar_df = df.copy()
copiar_df = copiar_df.drop('Tienda 1')
copiar_df


Out[24]:
Artículo comprado Costo Nombre
Tienda 2 Balón 5000 Jaime

In [26]:
copiar_df.drop?


Podemos eliminar una columna de manera sencilla, usando simplemente la palabra clave del y el índice o nombre de la comuna.


In [27]:
del copiar_df['Costo']
copiar_df


Out[27]:
Artículo comprado Nombre
Tienda 2 Balón Jaime


Finalmente, es muy sencillo agregar una columna al DataFrame.


In [28]:
df['Ubicación'] = ['Venezuela', 'Chile', 'Argentina']
df


Out[28]:
Artículo comprado Costo Nombre Ubicación
Tienda 1 Libro 1200 Adelis Venezuela
Tienda 1 Raspberry pi 3 15000 Miguel Chile
Tienda 2 Balón 5000 Jaime Argentina

Lectura de un DataFrame


Usemos !cat para leer un archivo de formato CSV. Nota: !cat funciona para Linux y Mac pero puede no funcionar para Windows :(


In [2]:
!cat olympics.csv


0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
,№ Summer,01 !,02 !,03 !,Total,№ Winter,01 !,02 !,03 !,Total,№ Games,01 !,02 !,03 !,Combined total
Afghanistan (AFG),13,0,0,2,2,0,0,0,0,0,13,0,0,2,2
Algeria (ALG),12,5,2,8,15,3,0,0,0,0,15,5,2,8,15
Argentina (ARG),23,18,24,28,70,18,0,0,0,0,41,18,24,28,70
Armenia (ARM),5,1,2,9,12,6,0,0,0,0,11,1,2,9,12
Australasia (ANZ) [ANZ],2,3,4,5,12,0,0,0,0,0,2,3,4,5,12
Australia (AUS) [AUS] [Z],25,139,152,177,468,18,5,3,4,12,43,144,155,181,480
Austria (AUT),26,18,33,35,86,22,59,78,81,218,48,77,111,116,304
Azerbaijan (AZE),5,6,5,15,26,5,0,0,0,0,10,6,5,15,26
Bahamas (BAH),15,5,2,5,12,0,0,0,0,0,15,5,2,5,12
Bahrain (BRN),8,0,0,1,1,0,0,0,0,0,8,0,0,1,1
Barbados (BAR) [BAR],11,0,0,1,1,0,0,0,0,0,11,0,0,1,1
Belarus (BLR),5,12,24,39,75,6,6,4,5,15,11,18,28,44,90
Belgium (BEL),25,37,52,53,142,20,1,1,3,5,45,38,53,56,147
Bermuda (BER),17,0,0,1,1,7,0,0,0,0,24,0,0,1,1
Bohemia (BOH) [BOH] [Z],3,0,1,3,4,0,0,0,0,0,3,0,1,3,4
Botswana (BOT),9,0,1,0,1,0,0,0,0,0,9,0,1,0,1
Brazil (BRA),21,23,30,55,108,7,0,0,0,0,28,23,30,55,108
British West Indies (BWI) [BWI],1,0,0,2,2,0,0,0,0,0,1,0,0,2,2
Bulgaria (BUL) [H],19,51,85,78,214,19,1,2,3,6,38,52,87,81,220
Burundi (BDI),5,1,0,0,1,0,0,0,0,0,5,1,0,0,1
Cameroon (CMR),13,3,1,1,5,1,0,0,0,0,14,3,1,1,5
Canada (CAN),25,59,99,121,279,22,62,56,52,170,47,121,155,173,449
Chile (CHI) [I],22,2,7,4,13,16,0,0,0,0,38,2,7,4,13
China (CHN) [CHN],9,201,146,126,473,10,12,22,19,53,19,213,168,145,526
Colombia (COL),18,2,6,11,19,1,0,0,0,0,19,2,6,11,19
Costa Rica (CRC),14,1,1,2,4,6,0,0,0,0,20,1,1,2,4
Ivory Coast (CIV) [CIV],12,0,1,0,1,0,0,0,0,0,12,0,1,0,1
Croatia (CRO),6,6,7,10,23,7,4,6,1,11,13,10,13,11,34
Cuba (CUB) [Z],19,72,67,70,209,0,0,0,0,0,19,72,67,70,209
Cyprus (CYP),9,0,1,0,1,10,0,0,0,0,19,0,1,0,1
Czech Republic (CZE) [CZE],5,14,15,15,44,6,7,9,8,24,11,21,24,23,68
Czechoslovakia (TCH) [TCH],16,49,49,45,143,16,2,8,15,25,32,51,57,60,168
Denmark (DEN) [Z],26,43,68,68,179,13,0,1,0,1,39,43,69,68,180
Djibouti (DJI) [B],7,0,0,1,1,0,0,0,0,0,7,0,0,1,1
Dominican Republic (DOM),13,3,2,1,6,0,0,0,0,0,13,3,2,1,6
Ecuador (ECU),13,1,1,0,2,0,0,0,0,0,13,1,1,0,2
Egypt (EGY) [EGY] [Z],21,7,9,10,26,1,0,0,0,0,22,7,9,10,26
Eritrea (ERI),4,0,0,1,1,0,0,0,0,0,4,0,0,1,1
Estonia (EST),11,9,9,15,33,9,4,2,1,7,20,13,11,16,40
Ethiopia (ETH),12,21,7,17,45,2,0,0,0,0,14,21,7,17,45
Finland (FIN),24,101,84,117,302,22,42,62,57,161,46,143,146,174,463
France (FRA) [O] [P] [Z],27,202,223,246,671,22,31,31,47,109,49,233,254,293,780
Gabon (GAB),9,0,1,0,1,0,0,0,0,0,9,0,1,0,1
Georgia (GEO),5,6,5,14,25,6,0,0,0,0,11,6,5,14,25
Germany (GER) [GER] [Z],15,174,182,217,573,11,78,78,53,209,26,252,260,270,782
United Team of Germany (EUA) [EUA],3,28,54,36,118,3,8,6,5,19,6,36,60,41,137
East Germany (GDR) [GDR],5,153,129,127,409,6,39,36,35,110,11,192,165,162,519
West Germany (FRG) [FRG],5,56,67,81,204,6,11,15,13,39,11,67,82,94,243
Ghana (GHA) [GHA],13,0,1,3,4,1,0,0,0,0,14,0,1,3,4
Great Britain (GBR) [GBR] [Z],27,236,272,272,780,22,10,4,12,26,49,246,276,284,806
Greece (GRE) [Z],27,30,42,39,111,18,0,0,0,0,45,30,42,39,111
Grenada (GRN),8,1,0,0,1,0,0,0,0,0,8,1,0,0,1
Guatemala (GUA),13,0,1,0,1,1,0,0,0,0,14,0,1,0,1
Guyana (GUY) [GUY],16,0,0,1,1,0,0,0,0,0,16,0,0,1,1
Haiti (HAI) [J],14,0,1,1,2,0,0,0,0,0,14,0,1,1,2
Hong Kong (HKG) [HKG],15,1,1,1,3,4,0,0,0,0,19,1,1,1,3
Hungary (HUN),25,167,144,165,476,22,0,2,4,6,47,167,146,169,482
Iceland (ISL),19,0,2,2,4,17,0,0,0,0,36,0,2,2,4
India (IND) [F],23,9,6,11,26,9,0,0,0,0,32,9,6,11,26
Indonesia (INA),14,6,10,11,27,0,0,0,0,0,14,6,10,11,27
Iran (IRI) [K],15,15,20,25,60,10,0,0,0,0,25,15,20,25,60
Iraq (IRQ),13,0,0,1,1,0,0,0,0,0,13,0,0,1,1
Ireland (IRL),20,9,8,12,29,6,0,0,0,0,26,9,8,12,29
Israel (ISR),15,1,1,5,7,6,0,0,0,0,21,1,1,5,7
Italy (ITA) [M] [S],26,198,166,185,549,22,37,34,43,114,48,235,200,228,663
Jamaica (JAM) [JAM],16,17,30,20,67,7,0,0,0,0,23,17,30,20,67
Japan (JPN),21,130,126,142,398,20,10,17,18,45,41,140,143,160,443
Kazakhstan (KAZ),5,16,17,19,52,6,1,3,3,7,11,17,20,22,59
Kenya (KEN),13,25,32,29,86,3,0,0,0,0,16,25,32,29,86
North Korea (PRK),9,14,12,21,47,8,0,1,1,2,17,14,13,22,49
South Korea (KOR),16,81,82,80,243,17,26,17,10,53,33,107,99,90,296
Kuwait (KUW),12,0,0,2,2,0,0,0,0,0,12,0,0,2,2
Kyrgyzstan (KGZ),5,0,1,2,3,6,0,0,0,0,11,0,1,2,3
Latvia (LAT),10,3,11,5,19,10,0,4,3,7,20,3,15,8,26
Lebanon (LIB),16,0,2,2,4,16,0,0,0,0,32,0,2,2,4
Liechtenstein (LIE),16,0,0,0,0,18,2,2,5,9,34,2,2,5,9
Lithuania (LTU),8,6,5,10,21,8,0,0,0,0,16,6,5,10,21
Luxembourg (LUX) [O],22,1,1,0,2,8,0,2,0,2,30,1,3,0,4
Macedonia (MKD),5,0,0,1,1,5,0,0,0,0,10,0,0,1,1
Malaysia (MAS) [MAS],12,0,3,3,6,0,0,0,0,0,12,0,3,3,6
Mauritius (MRI),8,0,0,1,1,0,0,0,0,0,8,0,0,1,1
Mexico (MEX),22,13,21,28,62,8,0,0,0,0,30,13,21,28,62
Moldova (MDA),5,0,2,5,7,6,0,0,0,0,11,0,2,5,7
Mongolia (MGL),12,2,9,13,24,13,0,0,0,0,25,2,9,13,24
Montenegro (MNE),2,0,1,0,1,2,0,0,0,0,4,0,1,0,1
Morocco (MAR),13,6,5,11,22,6,0,0,0,0,19,6,5,11,22
Mozambique (MOZ),9,1,0,1,2,0,0,0,0,0,9,1,0,1,2
Namibia (NAM),6,0,4,0,4,0,0,0,0,0,6,0,4,0,4
Netherlands (NED) [Z],25,77,85,104,266,20,37,38,35,110,45,114,123,139,376
Netherlands Antilles (AHO) [AHO] [I],13,0,1,0,1,2,0,0,0,0,15,0,1,0,1
New Zealand (NZL) [NZL],22,42,18,39,99,15,0,1,0,1,37,42,19,39,100
Niger (NIG),11,0,0,1,1,0,0,0,0,0,11,0,0,1,1
Nigeria (NGR),15,3,8,12,23,0,0,0,0,0,15,3,8,12,23
Norway (NOR) [Q],24,56,49,43,148,22,118,111,100,329,46,174,160,143,477
Pakistan (PAK),16,3,3,4,10,2,0,0,0,0,18,3,3,4,10
Panama (PAN),16,1,0,2,3,0,0,0,0,0,16,1,0,2,3
Paraguay (PAR),11,0,1,0,1,1,0,0,0,0,12,0,1,0,1
Peru (PER) [L],17,1,3,0,4,2,0,0,0,0,19,1,3,0,4
Philippines (PHI),20,0,2,7,9,4,0,0,0,0,24,0,2,7,9
Poland (POL),20,64,82,125,271,22,6,7,7,20,42,70,89,132,291
Portugal (POR),23,4,8,11,23,7,0,0,0,0,30,4,8,11,23
Puerto Rico (PUR),17,0,2,6,8,6,0,0,0,0,23,0,2,6,8
Qatar (QAT),8,0,0,4,4,0,0,0,0,0,8,0,0,4,4
Romania (ROU),20,88,94,119,301,20,0,0,1,1,40,88,94,120,302
Russia (RUS) [RUS],5,132,121,142,395,6,49,40,35,124,11,181,161,177,519
Russian Empire (RU1) [RU1],3,1,4,3,8,0,0,0,0,0,3,1,4,3,8
Soviet Union (URS) [URS],9,395,319,296,1010,9,78,57,59,194,18,473,376,355,1204
Unified Team (EUN) [EUN],1,45,38,29,112,1,9,6,8,23,2,54,44,37,135
Saudi Arabia (KSA),10,0,1,2,3,0,0,0,0,0,10,0,1,2,3
Senegal (SEN),13,0,1,0,1,5,0,0,0,0,18,0,1,0,1
Serbia (SRB) [SRB],3,1,2,4,7,2,0,0,0,0,5,1,2,4,7
Serbia and Montenegro (SCG) [SCG],3,2,4,3,9,3,0,0,0,0,6,2,4,3,9
Singapore (SIN),15,0,2,2,4,0,0,0,0,0,15,0,2,2,4
Slovakia (SVK) [SVK],5,7,9,8,24,6,2,2,1,5,11,9,11,9,29
Slovenia (SLO),6,4,6,9,19,7,2,4,9,15,13,6,10,18,34
South Africa (RSA),18,23,26,27,76,6,0,0,0,0,24,23,26,27,76
Spain (ESP) [Z],22,37,59,35,131,19,1,0,1,2,41,38,59,36,133
Sri Lanka (SRI) [SRI],16,0,2,0,2,0,0,0,0,0,16,0,2,0,2
Sudan (SUD),11,0,1,0,1,0,0,0,0,0,11,0,1,0,1
Suriname (SUR) [E],11,1,0,1,2,0,0,0,0,0,11,1,0,1,2
Sweden (SWE) [Z],26,143,164,176,483,22,50,40,54,144,48,193,204,230,627
Switzerland (SUI),27,47,73,65,185,22,50,40,48,138,49,97,113,113,323
Syria (SYR),12,1,1,1,3,0,0,0,0,0,12,1,1,1,3
Chinese Taipei (TPE) [TPE] [TPE2],13,2,7,12,21,11,0,0,0,0,24,2,7,12,21
Tajikistan (TJK),5,0,1,2,3,4,0,0,0,0,9,0,1,2,3
Tanzania (TAN) [TAN],12,0,2,0,2,0,0,0,0,0,12,0,2,0,2
Thailand (THA),15,7,6,11,24,3,0,0,0,0,18,7,6,11,24
Togo (TOG),9,0,0,1,1,1,0,0,0,0,10,0,0,1,1
Tonga (TGA),8,0,1,0,1,1,0,0,0,0,9,0,1,0,1
Trinidad and Tobago (TRI) [TRI],16,2,5,11,18,3,0,0,0,0,19,2,5,11,18
Tunisia (TUN),13,3,3,4,10,0,0,0,0,0,13,3,3,4,10
Turkey (TUR),21,39,25,24,88,16,0,0,0,0,37,39,25,24,88
Uganda (UGA),14,2,3,2,7,0,0,0,0,0,14,2,3,2,7
Ukraine (UKR),5,33,27,55,115,6,2,1,4,7,11,35,28,59,122
United Arab Emirates (UAE),8,1,0,0,1,0,0,0,0,0,8,1,0,0,1
United States (USA) [P] [Q] [R] [Z],26,976,757,666,2399,22,96,102,84,282,48,1072,859,750,2681
Uruguay (URU),20,2,2,6,10,1,0,0,0,0,21,2,2,6,10
Uzbekistan (UZB),5,5,5,10,20,6,1,0,0,1,11,6,5,10,21
Venezuela (VEN),17,2,2,8,12,4,0,0,0,0,21,2,2,8,12
Vietnam (VIE),14,0,2,0,2,0,0,0,0,0,14,0,2,0,2
Virgin Islands (ISV),11,0,1,0,1,7,0,0,0,0,18,0,1,0,1
Yugoslavia (YUG) [YUG],16,26,29,28,83,14,0,3,1,4,30,26,32,29,87
Independent Olympic Participants (IOP) [IOP],1,0,1,2,3,0,0,0,0,0,1,0,1,2,3
Zambia (ZAM) [ZAM],12,0,1,1,2,0,0,0,0,0,12,0,1,1,2
Zimbabwe (ZIM) [ZIM],12,3,4,1,8,1,0,0,0,0,13,3,4,1,8
Mixed team (ZZX) [ZZX],3,8,5,4,17,0,0,0,0,0,3,8,5,4,17
Totals,27,4809,4775,5130,14714,22,959,958,948,2865,49,5768,5733,6078,17579
hola


Pero ... no hay que preocuparse mucho por eso! Podemos leer este archivo en formato CSV en un DataFrame usando la función read_csv.


In [5]:
import pandas as pd
df = pd.read_csv('olympics.csv')
df.head()


Out[5]:
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
0 NaN № Summer 01 ! 02 ! 03 ! Total № Winter 01 ! 02 ! 03 ! Total № Games 01 ! 02 ! 03 ! Combined total
1 Afghanistan (AFG) 13 0 0 2 2 0 0 0 0 0 13 0 0 2 2
2 Algeria (ALG) 12 5 2 8 15 3 0 0 0 0 15 5 2 8 15
3 Argentina (ARG) 23 18 24 28 70 18 0 0 0 0 41 18 24 28 70
4 Armenia (ARM) 5 1 2 9 12 6 0 0 0 0 11 1 2 9 12


Aquí podemos ignorar la primera fila del DataFrame para dejar más limpia la tabla de información no relevante.


In [6]:
df = pd.read_csv('olympics.csv', index_col = 0, skiprows=1)
df.head()


Out[6]:
№ Summer 01 ! 02 ! 03 ! Total № Winter 01 !.1 02 !.1 03 !.1 Total.1 № Games 01 !.2 02 !.2 03 !.2 Combined total
Afghanistan (AFG) 13 0 0 2 2 0 0 0 0 0 13 0 0 2 2
Algeria (ALG) 12 5 2 8 15 3 0 0 0 0 15 5 2 8 15
Argentina (ARG) 23 18 24 28 70 18 0 0 0 0 41 18 24 28 70
Armenia (ARM) 5 1 2 9 12 6 0 0 0 0 11 1 2 9 12
Australasia (ANZ) [ANZ] 2 3 4 5 12 0 0 0 0 0 2 3 4 5 12


El atributo .columns nos permite ver el nombre de las comlumnas del DataFrame y el atributo .rename modificar el nombre.


In [7]:
df.columns


Out[7]:
Index(['№ Summer', '01 !', '02 !', '03 !', 'Total', '№ Winter', '01 !.1',
       '02 !.1', '03 !.1', 'Total.1', '№ Games', '01 !.2', '02 !.2', '03 !.2',
       'Combined total'],
      dtype='object')

In [8]:
for col in df.columns:
    if col[:2]=='01':
        df.rename(columns={col:'Gold' + col[4:]}, inplace=True)
    if col[:2]=='02':
        df.rename(columns={col:'Silver' + col[4:]}, inplace=True)
    if col[:2]=='03':
        df.rename(columns={col:'Bronze' + col[4:]}, inplace=True)
    if col[:1]=='№':
        df.rename(columns={col:'#' + col[1:]}, inplace=True) 

df.head()


Out[8]:
# Summer Gold Silver Bronze Total # Winter Gold.1 Silver.1 Bronze.1 Total.1 # Games Gold.2 Silver.2 Bronze.2 Combined total
Afghanistan (AFG) 13 0 0 2 2 0 0 0 0 0 13 0 0 2 2
Algeria (ALG) 12 5 2 8 15 3 0 0 0 0 15 5 2 8 15
Argentina (ARG) 23 18 24 28 70 18 0 0 0 0 41 18 24 28 70
Armenia (ARM) 5 1 2 9 12 6 0 0 0 0 11 1 2 9 12
Australasia (ANZ) [ANZ] 2 3 4 5 12 0 0 0 0 0 2 3 4 5 12

Haciendo búsquedas en un DataFrame


Podemos buscar en el DataFrame con una máscara Booleana qué países tienen (True) o no (False) una medalla de oro.


In [9]:
df['Gold'] > 0


Out[9]:
Afghanistan (AFG)                               False
Algeria (ALG)                                    True
Argentina (ARG)                                  True
Armenia (ARM)                                    True
Australasia (ANZ) [ANZ]                          True
Australia (AUS) [AUS] [Z]                        True
Austria (AUT)                                    True
Azerbaijan (AZE)                                 True
Bahamas (BAH)                                    True
Bahrain (BRN)                                   False
Barbados (BAR) [BAR]                            False
Belarus (BLR)                                    True
Belgium (BEL)                                    True
Bermuda (BER)                                   False
Bohemia (BOH) [BOH] [Z]                         False
Botswana (BOT)                                  False
Brazil (BRA)                                     True
British West Indies (BWI) [BWI]                 False
Bulgaria (BUL) [H]                               True
Burundi (BDI)                                    True
Cameroon (CMR)                                   True
Canada (CAN)                                     True
Chile (CHI) [I]                                  True
China (CHN) [CHN]                                True
Colombia (COL)                                   True
Costa Rica (CRC)                                 True
Ivory Coast (CIV) [CIV]                         False
Croatia (CRO)                                    True
Cuba (CUB) [Z]                                   True
Cyprus (CYP)                                    False
                                                ...  
Sri Lanka (SRI) [SRI]                           False
Sudan (SUD)                                     False
Suriname (SUR) [E]                               True
Sweden (SWE) [Z]                                 True
Switzerland (SUI)                                True
Syria (SYR)                                      True
Chinese Taipei (TPE) [TPE] [TPE2]                True
Tajikistan (TJK)                                False
Tanzania (TAN) [TAN]                            False
Thailand (THA)                                   True
Togo (TOG)                                      False
Tonga (TGA)                                     False
Trinidad and Tobago (TRI) [TRI]                  True
Tunisia (TUN)                                    True
Turkey (TUR)                                     True
Uganda (UGA)                                     True
Ukraine (UKR)                                    True
United Arab Emirates (UAE)                       True
United States (USA) [P] [Q] [R] [Z]              True
Uruguay (URU)                                    True
Uzbekistan (UZB)                                 True
Venezuela (VEN)                                  True
Vietnam (VIE)                                   False
Virgin Islands (ISV)                            False
Yugoslavia (YUG) [YUG]                           True
Independent Olympic Participants (IOP) [IOP]    False
Zambia (ZAM) [ZAM]                              False
Zimbabwe (ZIM) [ZIM]                             True
Mixed team (ZZX) [ZZX]                           True
Totals                                           True
Name: Gold, Length: 147, dtype: bool


La función .where() toma una máscara booleana como condición en el argumento, la aplica al DataFrame, y devuelve un DataFrame de la misma forma. En nuestro ejemplo, reemplaza con NaN los casos False y con su valor original, los casos True.


In [10]:
only_gold = df.where(df['Gold'] > 0)
only_gold.head()


Out[10]:
# Summer Gold Silver Bronze Total # Winter Gold.1 Silver.1 Bronze.1 Total.1 # Games Gold.2 Silver.2 Bronze.2 Combined total
Afghanistan (AFG) NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
Algeria (ALG) 12.0 5.0 2.0 8.0 15.0 3.0 0.0 0.0 0.0 0.0 15.0 5.0 2.0 8.0 15.0
Argentina (ARG) 23.0 18.0 24.0 28.0 70.0 18.0 0.0 0.0 0.0 0.0 41.0 18.0 24.0 28.0 70.0
Armenia (ARM) 5.0 1.0 2.0 9.0 12.0 6.0 0.0 0.0 0.0 0.0 11.0 1.0 2.0 9.0 12.0
Australasia (ANZ) [ANZ] 2.0 3.0 4.0 5.0 12.0 0.0 0.0 0.0 0.0 0.0 2.0 3.0 4.0 5.0 12.0


Podemos contar cuántas países hay medallas de oro hay en total con count()


In [11]:
only_gold['Gold'].count()


Out[11]:
100

Si contamos sobre los datos originales, veremos que hay 147 países. Cuenta los países para los cuales la máscara Booleana dio False >.<


In [12]:
df['Gold'].count()


Out[12]:
147


Podemos establecer otro tipo de condiciones para hacer búsquedas más complejas. Por ejemplo, buscar la cantidad de países que han ganado medalla de oro alguna vez.


In [15]:
len(df[(df['Gold'] > 0) | (df['Gold.1'] > 0)])


Out[15]:
101


Buscar qué países han ganado sólo medallas de oro en Invierno y nunca en Verano.


In [16]:
df[(df['Gold.1'] > 0) & (df['Gold'] == 0)]


Out[16]:
# Summer Gold Silver Bronze Total # Winter Gold.1 Silver.1 Bronze.1 Total.1 # Games Gold.2 Silver.2 Bronze.2 Combined total
Liechtenstein (LIE) 16 0 0 0 0 18 2 2 5 9 34 2 2 5 9

In [ ]: